﻿using AutoMapper;
using QYmall.Core.API.Filters;
using QYmall.Core.Common.Emum;
using QYmall.Core.Common.Extensions;
using QYmall.Core.Common.Helper;
using QYmall.Core.IServices;
using QYmall.Core.Model.Models;
using QYmall.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.AspNetCore.Mvc;

namespace QYmall.Core.API.Controllers
{
    /// <summary>
    /// 商户信息
    /// </summary>
    [Route("admin/merchant")]
    [ApiController]
    public class MerchantController : ControllerBase
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IMerchantService _merchantService;
        private readonly IUserService _userService;
        private readonly ISysConfigService _sysConfigService;
        private readonly IMapper _mapper;

        /// <summary>
        /// 依赖注入
        /// </summary>
        public MerchantController(IMerchantService merchantService, IUserService userService,
            ISysConfigService sysConfigService, IHttpContextAccessor httpContextAccessor, IMapper mapper)
        {
            _merchantService = merchantService;
            _userService = userService;
            _sysConfigService = sysConfigService;
            _httpContextAccessor = httpContextAccessor;
            _mapper = mapper;
        }

        #region 管理员调用接口==========================
        /// <summary>
        /// 根据ID获取一条记录
        /// 示例：/admin/merchant/1
        /// </summary>
        [HttpGet("{id}")]
        [Authorize]
        [AuthorizeFilter("Merchant", ActionType.View)]
        public async Task<IActionResult> GetById([FromRoute] int id, [FromQuery] MerchantParameter param)
        {
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<MerchantsDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //查询数据库获取实体
            var model = await _merchantService.QueryAsync(x => x.Id == id, WriteRoRead.Write);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"商户{id}不存在或已删除"));
            }
            //根据字段进行塑形
            var result = _mapper.Map<MerchantsDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 获取总记录数量
        /// 示例：/admin/merchant/view/count
        /// </summary>
        [HttpGet("view/count")]
        [Authorize]
        [AuthorizeFilter("Merchant", ActionType.View)]
        public async Task<IActionResult> GetCount([FromQuery] MerchantParameter searchParam)
        {
            var result = await _merchantService.QueryCountAsync(
                x => searchParam.Status < 0 || (x.IsLock == searchParam.Status));
            //返回成功200
            return Ok(result);
        }

        /// <summary>
        /// 获取指定数量列表
        /// 示例：/admin/merchant/view/10
        /// </summary>
        [HttpGet("view/{top}")]
        [Authorize]
        [AuthorizeFilter("Article", ActionType.View)]
        public async Task<IActionResult> GetList([FromRoute] int top, [FromQuery] BaseParameter searchParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy != null
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<MerchantsDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<MerchantsDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据库列表
            var resultFrom = await _merchantService.QueryListAsync(top,
                x => (searchParam.Status < 0 || x.IsLock == searchParam.Status)
                && (!searchParam.Keyword.IsNotNullOrEmpty() || (x.Title != null && x.Title.Contains(searchParam.Keyword))),
                searchParam.OrderBy ?? "SortId,-Id");

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<MerchantsDto>>(resultFrom).ShapeData(searchParam.Fields);
            //返回成功200
            return Ok(resultDto);
        }

        // <summary>
        /// 获取分页列表
        /// 示例：/admin/merchant?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet]
        [Authorize]
        [AuthorizeFilter("Merchant", ActionType.View)]
        public async Task<IActionResult> GetList([FromQuery] MerchantParameter searchParam, [FromQuery] PageParamater pageParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy != null
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<MerchantsDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<MerchantsDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据列表
            var list = await _merchantService.QueryPageAsync(
                pageParam.PageSize,
                pageParam.PageIndex,
                x => (searchParam.Status < 0 || x.IsLock == searchParam.Status)
                && (!searchParam.Keyword.IsNotNullOrEmpty()
                    || (x.Title != null && x.Title.Contains(searchParam.Keyword))
                    || (x.User != null && x.User.UserName.Contains(searchParam.Keyword))
                    || (x.User != null && x.User.PhoneNumber.Contains(searchParam.Keyword))),
                searchParam.OrderBy ?? "-Id,-AddTime");

            //x-pagination
            var paginationMetadata = new
            {
                totalCount = list.TotalCount,
                pageSize = list.PageSize,
                pageIndex = list.PageIndex,
                totalPages = list.TotalPages
            };
            Response.Headers.Add("x-pagination", SerializeHelper.SerializeObject(paginationMetadata));

            //映射成DTO
            var resultDto = _mapper.Map<IEnumerable<MerchantsDto>>(list).ShapeData(searchParam.Fields);
            return Ok(resultDto);
        }

        /// <summary>
        /// 添加一条记录
        /// 示例：/admin/merchant
        /// </summary>
        [HttpPost]
        [Authorize]
        [AuthorizeFilter("Merchant", ActionType.Add)]
        public async Task<IActionResult> Add([FromBody] MerchantsEditDto modelDto)
        {
            var result = await _merchantService.AddAsync(modelDto);
            return Ok(result);
        }

        /// <summary>
        /// 修改一条记录
        /// 示例：/admin/merchant/1
        /// </summary>
        [HttpPut("{id}")]
        [Authorize]
        [AuthorizeFilter("Merchant", ActionType.Edit)]
        public async Task<IActionResult> Update([FromRoute] int id, [FromBody] MerchantsEditDto modelDto)
        {
            var result = await _merchantService.UpdateAsync(id, modelDto);
            return NoContent();
        }

        /// <summary>
        /// 局部更新一条记录
        /// 示例：/admin/merchant/1
        /// Body：[{"op":"replace","path":"/title","value":"new title"}]
        /// </summary>
        [HttpPatch("{id}")]
        [Authorize]
        [AuthorizeFilter("Merchant", ActionType.Edit)]
        public async Task<IActionResult> Update([FromRoute] int id, [FromBody] JsonPatchDocument<MerchantsEditDto> patchDocument)
        {
            var model = await _merchantService.QueryAsync<Merchants>(x => x.Id == id, WriteRoRead.Write);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }

            var modelToPatch = _mapper.Map<MerchantsEditDto>(model);
            patchDocument.ApplyTo(modelToPatch, ModelState);
            //验证数据是否合法
            if (!TryValidateModel(modelToPatch))
            {
                return ValidationProblem(ModelState);
            }
            //更新操作AutoMapper替我们完成，只需要调用保存即可
            _mapper.Map(modelToPatch, model);
            await _merchantService.SaveAsync();
            return NoContent();
        }

        /// <summary>
        /// 删除一条记录
        /// 示例：/admin/merchant/1
        /// </summary>
        [HttpDelete("{id}")]
        [Authorize]
        [AuthorizeFilter("Merchant", ActionType.Delete)]
        public async Task<IActionResult> Delete([FromRoute] int id)
        {
            //查找记录是否存在
            if (!await _merchantService.ExistsAsync<Merchants>(x => x.Id == id))
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            var result = await _merchantService.DeleteAsync<Merchants>(x => x.Id == id);

            return NoContent();
        }

        /// <summary>
        /// 批量删除记录(级联数据)
        /// 示例：/admin/merchant?ids=1,2,3
        /// </summary>
        [HttpDelete]
        [Authorize]
        [AuthorizeFilter("Merchant", ActionType.Delete)]
        public async Task<IActionResult> DeleteByIds([FromQuery] string Ids)
        {
            if (Ids == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不可为空"));
            }
            //将ID列表转换成IEnumerable
            var listIds = Ids.ToIEnumerable<int>();
            if (listIds == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不符合规范"));
            }
            //执行批量删除操作
            var result = await _merchantService.DeleteAsync<Merchants>(x => listIds.Contains(x.Id));
            return NoContent();
        }

        /// <summary>
        /// 批量审核记录
        /// 示例：/admin/merchant/audit
        /// </summary>
        [HttpPut("audit")]
        [Authorize]
        [AuthorizeFilter("Merchant", ActionType.Audit)]
        public async Task<IActionResult> Audit([FromQuery] string Ids)
        {
            if (Ids == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不可为空"));
            }
            //将ID列表转换成IEnumerable
            var listIds = Ids.ToIEnumerable<int>();
            if (listIds == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不符合规范"));
            }
            //将符合条件的用户ID一次查询出来
            var list = await _merchantService.QueryListAsync<Merchants>(0,
                x => x.IsLock == 1 && listIds.Contains(x.Id), "-AddTime,-Id", WriteRoRead.Write);
            //执行批量操作
            foreach (var item in list)
            {
                item.IsLock = 0;
            }
            var result = await _merchantService.SaveAsync();
            return NoContent();
        }
        #endregion

        #region 商家调用接口============================
        /// <summary>
        /// 获取当前商户信息
        /// 示例：/merchant
        /// </summary>
        [HttpGet("/merchant")]
        [Authorize]
        public async Task<IActionResult> MerchantGetById([FromQuery] MemberParameter param)
        {
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<MerchantsDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //获取登录用户ID
            int userId = await _userService.GetUserIdAsync();
            if (userId == 0)
            {
                return BadRequest(ResponseMessage.Error("用户尚未登录"));
            }
            //查询数据库获取实体
            var model = await _merchantService.QueryAsync(x => x.UserId == userId, WriteRoRead.Write);
            if (model == null)
            {
                return Unauthorized(ResponseMessage.Error("尚未开通商户功能，请检查重试"));
            }
            if (model.IsLock != 0)
            {
                return Unauthorized(ResponseMessage.Error("商户尚未开通，请等待审核通过"));
            }
            //根据字段进行塑形
            var result = _mapper.Map<MerchantsDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 修改当前商户信息
        /// 示例：/merchant
        /// </summary>
        [HttpPut("/merchant")]
        [Authorize]
        public async Task<IActionResult> MerchantUpdate([FromBody] MerchantsBaseDto modelDto)
        {
            //获取登录用户ID
            int userId = await _userService.GetUserIdAsync();
            if (userId == 0)
            {
                return BadRequest(ResponseMessage.Error("用户尚未登录"));
            }
            var model = await _merchantService.QueryAsync<Merchants>(x => x.UserId == userId, WriteRoRead.Write);
            if (model == null)
            {
                return Unauthorized(ResponseMessage.Error("尚未开通商户功能，请检查重试"));
            }
            if (model.IsLock != 0)
            {
                return Unauthorized(ResponseMessage.Error("商户尚未开通，请等待审核通过"));
            }
            _mapper.Map(modelDto, model);
            await _merchantService.SaveAsync();
            return NoContent();
        }

        /// <summary>
        /// 修改当前商户密码
        /// 示例：/merchant/password
        /// </summary>
        [HttpPut("/merchant/password")]
        [Authorize]
        public async Task<IActionResult> MerchantPassword([FromBody] PasswordDto modelDto)
        {
            await _userService.UpdatePasswordAsync(modelDto);
            return NoContent();
        }
        #endregion

        #region 普通账户调用接口========================
        /// <summary>
        /// 根据ID获取一条记录
        /// 示例：/account/merchant
        /// </summary>
        [HttpGet("/account/merchant")]
        [Authorize]
        public async Task<IActionResult> ClientGetById([FromQuery] MerchantParameter param)
        {
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<MerchantsDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //获取登录用户ID
            int userId = await _userService.GetUserIdAsync();

            //查询数据库获取实体
            var model = await _merchantService.QueryAsync(x => x.UserId == userId, WriteRoRead.Write);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"获取不到当前用户店铺信息"));
            }
            //根据字段进行塑形
            var result = _mapper.Map<MerchantsDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 商户申请
        /// 示例：/account/merchant
        /// </summary>
        [HttpPost("/account/merchant")]
        [Authorize]
        public async Task<IActionResult> AccountAdd([FromBody] MerchantsBaseDto baseDto)
        {
            //获取登录用户ID
            int userId = await _userService.GetUserIdAsync();
            //获取商家信息
            var merchantModel = await _merchantService.QueryAsync<Merchants>(x => x.UserId == userId);
            if (merchantModel != null)
            {
                return BadRequest(ResponseMessage.Error("当前用户已成为商户，请勿重复申请"));
            }

            //取得商户参数设置
            var jsonData = await _sysConfigService.QueryByTypeAsync(ConfigType.MerchantConfig);
            var merchantConfig = JsonHelper.ToJson<MerchantConfigDto>(jsonData?.JsonData);
            //检查商户是否开放申请
            if (merchantConfig?.RegStatus == 1)
            {
                throw new ResponseException("系统暂停申请商户，请稍候再试");
            }
            //将基础的DTO映射成修改DTO
            var modelDto = _mapper.Map<MerchantsEditDto>(baseDto);
            modelDto.UserId = userId;
            modelDto.TradeFee = null;//使用分类的交易费百分比
            //是否开启人工审核
            if (merchantConfig?.RegVerify == 1)
            {
                modelDto.IsLock = 1;
            }
            else
            {
                modelDto.IsLock = 0;
            }

            var result = await _merchantService.AddAsync(modelDto);
            return Ok(result);
        }

        /// <summary>
        /// 修改申请
        /// 示例：/account/merchant
        /// </summary>
        [HttpPut("/account/merchant")]
        [Authorize]
        public async Task<IActionResult> AccountUpdate([FromBody] MerchantsBaseDto modelDto)
        {
            //获取登录用户ID
            int userId = await _userService.GetUserIdAsync();
            if (userId == 0)
            {
                return BadRequest(ResponseMessage.Error("用户尚未登录"));
            }
            var model = await _merchantService.QueryAsync<Merchants>(x => x.UserId == userId, WriteRoRead.Write);
            if (model == null)
            {
                return Unauthorized(ResponseMessage.Error("尚未开通商户功能，请检查重试"));
            }
            if (model.IsLock == 0)
            {
                return BadRequest(ResponseMessage.Error("您已成为商户，请进入商户平台修改资料"));
            }
            if (model.IsLock == 1)
            {
                return BadRequest(ResponseMessage.Error("已提交申请，请等待审核通过"));
            }
            model.IsLock = 1; //待审核
            _mapper.Map(modelDto, model);
            await _merchantService.SaveAsync();
            return NoContent();
        }
        #endregion

        #region 前台调用接口============================
        /// <summary>
        /// 根据ID获取一条记录
        /// 示例：/client/merchant/1
        /// </summary>
        [HttpGet("/client/merchant/{id}")]
        public async Task<IActionResult> ClientGetById([FromRoute] int id, [FromQuery] MerchantParameter param)
        {
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<MerchantsClientDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //查询数据库获取实体
            var model = await _merchantService.QueryAsync(x => x.Id == id, WriteRoRead.Write);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"商户{id}不存在或已删除"));
            }
            //根据字段进行塑形
            var result = _mapper.Map<MerchantsClientDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 获取指定数量列表
        /// 示例：/client/merchant/view/10
        /// </summary>
        [HttpGet("/client/merchant/view/{top}")]
        public async Task<IActionResult> ClientGetList([FromRoute] int top, [FromQuery] BaseParameter searchParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy != null
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<MerchantsClientDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<MerchantsClientDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据库列表
            var resultFrom = await _merchantService.QueryListAsync(top,
                x => x.IsLock == 0
                && (!searchParam.Keyword.IsNotNullOrEmpty() || (x.Title != null && x.Title.Contains(searchParam.Keyword))),
                searchParam.OrderBy ?? "SortId,-Id");

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<MerchantsClientDto>>(resultFrom).ShapeData(searchParam.Fields);
            //返回成功200
            return Ok(resultDto);
        }

        // <summary>
        /// 获取分页列表
        /// 示例：/client/merchant?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet("/client/merchant")]
        public async Task<IActionResult> ClientGetList([FromQuery] MerchantParameter searchParam, [FromQuery] PageParamater pageParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy != null
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<MerchantsClientDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<MerchantsClientDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据列表
            var list = await _merchantService.QueryPageAsync(
                pageParam.PageSize,
                pageParam.PageIndex,
                x => x.IsLock == 0
                && (!searchParam.Keyword.IsNotNullOrEmpty() || (x.Title != null && x.Title.Contains(searchParam.Keyword))),
                searchParam.OrderBy ?? "-Id,-AddTime");

            //x-pagination
            var paginationMetadata = new
            {
                totalCount = list.TotalCount,
                pageSize = list.PageSize,
                pageIndex = list.PageIndex,
                totalPages = list.TotalPages
            };
            Response.Headers.Add("x-pagination", SerializeHelper.SerializeObject(paginationMetadata));

            //映射成DTO
            var resultDto = _mapper.Map<IEnumerable<MerchantsClientDto>>(list).ShapeData(searchParam.Fields);
            return Ok(resultDto);
        }

        // <summary>
        /// 获取分页列表(带商品)
        /// 示例：/client/merchant/goods/10?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet("/client/merchant/goods/{top}")]
        public async Task<IActionResult> ClientGoodsList([FromRoute] int top, [FromQuery] MerchantParameter searchParam, [FromQuery] PageParamater pageParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy != null
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<MerchantsGoodsClientDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<MerchantsGoodsClientDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //限制显示商品数量
            if (top <= 0 || top > 10)
            {
                top = 10;
            }

            //获取数据列表
            var list = await _merchantService.QueryGoodsPageAsync(
                top,
                pageParam.PageSize,
                pageParam.PageIndex,
                x => x.IsLock == 0
                && (!searchParam.Keyword.IsNotNullOrEmpty() || (x.Title != null && x.Title.Contains(searchParam.Keyword))),
                searchParam.OrderBy ?? "SortId,-AddTime");

            //x-pagination
            var paginationMetadata = new
            {
                totalCount = list.TotalCount,
                pageSize = list.PageSize,
                pageIndex = list.PageIndex,
                totalPages = list.TotalPages
            };
            Response.Headers.Add("x-pagination", SerializeHelper.SerializeObject(paginationMetadata));

            //映射成DTO
            var resultDto = _mapper.Map<IEnumerable<MerchantsGoodsClientDto>>(list).ShapeData(searchParam.Fields);
            return Ok(resultDto);
        }
        #endregion
    }
}
